package com.example.demo.utils;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.example.demo.domain.TextEntity;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.*;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.VerticalAlignment;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Date;

@Slf4j
public class WatermarkUtils {

    public static void main(String[] args) throws Exception {
        String input = "E:/Users/Desktop/项目/input.pdf";
        String output = "E:/Users/Desktop/项目/output.pdf";
        long start = System.currentTimeMillis();
        byte[] watermark = ImageUtils.readResourceAsByteArray("image/spdb_3.png");
        PdfDocument pdfDocument = new PdfDocument(new PdfReader(input), new PdfWriter(output));
        watermarkAndQrCode(pdfDocument, watermark, "浦发银行" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN));
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

    public static void watermarkAndQrCode(PdfDocument pdfDoc, byte[] watermark, String qrCodeContent) throws Exception {
        // 生成水印图片
        ImageData imageData = ImageDataFactory.create(watermark);
//        PdfImageXObject imageXObject = new PdfImageXObject(imageData);
        // 循环写入水印和二维码
        for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
            PdfPage page = pdfDoc.getPage(i);
            PageSize pageSize = page.getDocument().getDefaultPageSize();
            // 画图
            PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
            // 添加水印
            addImageWatermark(pageSize, pdfCanvas, imageData, 100, false);
            // 添加二维码
//            QrCodeUtils.addPdf417Code(page, pageSize, qrCodeContent + "_浦發_" + i);
        }
        pdfDoc.close();
    }

    public static void watermarkImg(PdfDocument pdfDoc, byte[] watermark) throws Exception {
        // 读取图片
        Image image = new Image(ImageDataFactory.create(watermark));
        // 循环写入水印图片
        for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
            PdfPage page = pdfDoc.getPage(i);
            PageSize pageSize = page.getDocument().getDefaultPageSize();
            // 添加水印
            addImageWatermark(page, pageSize, image);
        }
        pdfDoc.close();
    }

    public static void watermarkText(PdfDocument pdfDoc, String text) throws Exception {
        // 调用
        watermarkText(pdfDoc, new TextEntity(text));
    }

    public static void watermarkText(PdfDocument pdfDoc, TextEntity textEntity) throws Exception {
        // 初始化PDF文档
        int numberOfPages = pdfDoc.getNumberOfPages();
        // 默认字体
        if (textEntity.getFont() == null) {
            textEntity.setFont(PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H"));
        }
        // 循环写入水印图片
        for (int i = 1; i <= numberOfPages; i++) {
            PdfPage page = pdfDoc.getPage(i);
            PageSize pageSize = page.getDocument().getDefaultPageSize();
            // 添加水印
            addTiledWatermark(page, pageSize, numberOfPages, textEntity);
        }
        pdfDoc.close();
    }

    public static PdfReader getPdfReader(String input) throws Exception {
        return new PdfReader(input);
    }

    public static PdfReader getPdfReader(File input) throws Exception {
        return new PdfReader(input);
    }

    public static PdfReader getPdfReader(InputStream input) throws Exception {
        return new PdfReader(input);
    }

    public static PdfWriter getPdfWriter(String output) throws Exception {
        return new PdfWriter(output);
    }

    public static PdfWriter getPdfWriter(File output) throws Exception {
        return new PdfWriter(output);
    }

    public static PdfWriter getPdfWriter(OutputStream output) throws Exception {
        return new PdfWriter(output);
    }

    public static byte[] readWatermark(String watermark) throws Exception {
        return Files.readAllBytes(Paths.get(watermark));
    }

    public static byte[] readWatermark(File watermark) throws Exception {
        return Files.readAllBytes(Paths.get(watermark.getAbsolutePath()));
    }

    public static byte[] readWatermark(InputStream watermark) throws Exception {
        return toByteArray(watermark);
    }

    private static PdfDocument createPdfDocument(PdfReader reader, PdfWriter writer) throws Exception {
        // 初始化PDF文档
        return new PdfDocument(reader, writer);
    }

    private static byte[] toByteArray(InputStream inputStream) throws Exception {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        int nRead;
        byte[] data = new byte[4096];
        while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, nRead);
        }
        buffer.flush();
        return buffer.toByteArray();
    }

    private static void addImageWatermark(PageSize pageSize, PdfCanvas canvas, ImageData imageData, int offsetY, boolean inline) throws Exception {
        // 页面尺寸
        float pageWidth = pageSize.getWidth();
        float pageHeight = pageSize.getHeight();
        // 图片尺寸
        float imageWidth = imageData.getWidth();
        float imageHeight = imageData.getHeight();
        // 图片占用空间
        float seatWidth = imageWidth * 2.3f;
        float seatHeight = imageHeight * 3.5f;
        // 计算行列
        int columns = (int) Math.ceil(pageWidth / seatWidth);
        int rows = (int) Math.ceil(pageHeight / seatHeight);
        // 旋转角度
//        double rotation = Math.toRadians(45);
        // 透明度
//        canvas.setExtGState(new PdfExtGState().setFillOpacity(0.1f).setStrokeOpacity(0.1f));
        // 平铺水印
        for (int col = 0; col < columns; col++) {
            boolean isOffset = col % 2 != 0;
            float x = (seatWidth - imageWidth) / 2 + seatWidth * col;
            for (int row = 0; row < rows; row++) {
                float y = (seatHeight - imageHeight) / 2 + seatHeight * row + (isOffset ? offsetY : 0);
                canvas.addImageAt(imageData, x, y, inline);
            }
        }
    }

    private static void addImageWatermark(PdfPage page, PageSize pageSize, Image watermark) {
        float imgWidth = watermark.getImageWidth();
        float imgHeight = watermark.getImageHeight();
        float xStep = imgWidth * 1.5f;
        float yStep = imgHeight * 1.5f;

        Canvas canvas = new Canvas(page, pageSize);
        for (float x = 0; x < pageSize.getWidth(); x += xStep) {
            for (float y = 0; y < pageSize.getHeight(); y += yStep) {
                watermark.setFixedPosition(x, y);
                canvas.add(watermark);
            }
        }
        // 关闭canvas
        canvas.close();
    }

    private static void addTiledWatermark(PdfPage page, PageSize pageSize, int numberOfPages, TextEntity textEntity) throws Exception {
        // 创建Canvas对象用于绘制
        Canvas canvas = new Canvas(page, pageSize);
        // 设置不可选属性
        PdfCanvas pdfCanvas = canvas.getPdfCanvas();
        pdfCanvas.beginMarkedContent(PdfName.Artifact);
        // 透明度
        PdfExtGState gs = new PdfExtGState().setFillOpacity(textEntity.getOpacity()).setStrokeOpacity(textEntity.getOpacity());
        pdfCanvas.setExtGState(gs);
        // 水印参数
        float angle = (float) Math.toRadians(textEntity.getAngle());
        // 计算平铺范围
        float width = pageSize.getWidth() + pageSize.getHeight();
        float height = pageSize.getHeight() + pageSize.getWidth();
        // 平铺绘制循环
        for (float x = -height; x < width; x += textEntity.getXStep()) {
            for (float y = 0; y < height; y += textEntity.getYStep()) {
                Paragraph paragraph = new Paragraph(textEntity.getText())
                        .setFont(textEntity.getFont())
                        .setFontSize(textEntity.getFontsize())
                        .setFontColor(textEntity.getColor());
                canvas.showTextAligned(paragraph, x, y, numberOfPages, TextAlignment.CENTER, VerticalAlignment.MIDDLE, angle);
            }
        }
        pdfCanvas.endMarkedContent();
        // 关闭canvas
        canvas.close();
    }

}
